package com.habdqn.studentmanager.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;

import javax.annotation.Resource;
import javax.transaction.Transactional;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.github.stuxuhai.jpinyin.PinyinException;
import com.github.stuxuhai.jpinyin.PinyinFormat;
import com.github.stuxuhai.jpinyin.PinyinHelper;
import com.github.xiaofan1519.verify.core.Verify;
import com.github.xiaofan1519.verify.exception.VerifyException;
import com.habdqn.studentmanager.bean.Classes;
import com.habdqn.studentmanager.bean.Dictionary;
import com.habdqn.studentmanager.bean.Product;
import com.habdqn.studentmanager.bean.Student;
import com.habdqn.studentmanager.constant.ClassType;
import com.habdqn.studentmanager.constant.DictType;
import com.habdqn.studentmanager.constant.LogType;
import com.habdqn.studentmanager.controller.StudentController;
import com.habdqn.studentmanager.exception.StudentException;
import com.habdqn.studentmanager.mapper.StudentMapper;
import com.habdqn.studentmanager.service.ClassesService;
import com.habdqn.studentmanager.service.DictionaryService;
import com.habdqn.studentmanager.service.StudentService;
import com.habdqn.studentmanager.util.ConfigUtil;
import com.habdqn.studentmanager.util.DateUtil;
import com.habdqn.studentmanager.util.ExcelUtil;
import com.habdqn.studentmanager.util.ExcelUtil.Excel.Cell;
import com.habdqn.studentmanager.util.ExcelUtil.Excel.Row;
import com.habdqn.studentmanager.util.ProjectUtil;
import com.habdqn.studentmanager.util.SystemLogger;

/**
 * @author Administrator
 * 
 * 2017年5月19日
 * 
 */
@Service
public class StudentServiceImpl implements StudentService {

	private static Logger logger = LoggerFactory.getLogger(StudentServiceImpl.class);
	
	@Resource
	private StudentMapper studentMapper;
	
	@Resource
	private SystemLogger systemLogger;
	
	@Resource
	private ClassesService classService;
	
	@Resource
	private DictionaryService dictService;
	
	@Override
	public void insert(Student bean) {
		
		try {
			String pinyin = PinyinHelper.convertToPinyinString(bean.getName(), " ", PinyinFormat.WITHOUT_TONE);
			bean.setPinyin(pinyin);
		}
		catch (PinyinException e) {
			logger.error("拼音转换失败. name:" + bean.getName(), e);
		}
		
		try {
			Classes clazz = bean.getClasses();
			// 班级为非必填
			if (null != clazz && StringUtils.isNotEmpty(clazz.getName())) {
				classService.find(clazz);
			}
			
			studentMapper.insert(bean);
			systemLogger.record(LogType.AddType, "新增学生 编号:" + bean.getId());
		}
		catch (DuplicateKeyException e) {
			logger.debug("duplicateKey: {}", bean.getId(), e);
			throw new StudentException("学号重复，请重新输入", e);
		}
		catch (Exception e) {
			logger.error("system error", e);
			throw new StudentException("新增学生失败", e);
		}
	}

	@Override
	public void update(Student bean) {
		
		try {
			Classes clazz = bean.getClasses();
			// 校验班级是否正确
			if (null != clazz && StringUtils.isNotEmpty(clazz.getName())) {
				classService.find(clazz);
			}

			Student s = studentMapper.find(bean);
			//如果学生是退学状态则状态不可改
			if(ClassType.leave.toInteger().equals(s.getStatus())){
				if(!ClassType.leave.toInteger().equals(bean.getStatus())){
					logger.debug("退学的学生状态不可改");
					throw new StudentException("退学的学生状态不可改");
				}
			}
			
			//修改班级时修改学生状态为正常
			if(!equalsClass(s.getClasses(), bean.getClasses())){
				if(ClassType.suspend.toInteger().equals(s.getStatus())){
					bean.setStatus(ClassType.normal.toInteger());
				}
			}			
			studentMapper.update(bean);
			systemLogger.record(LogType.UpdateType, "更新学员信息:" + bean.getId());
		}
		catch (Exception e) {
			logger.error("system error", e);
			throw new StudentException("更新学生信息失败", e);
		}
	}
	
	/**
	 * 判断两个班级是否相等
	 * @param left
	 * @param right
	 * @return
	 */
	private boolean equalsClass(Classes left, Classes right) {
		String leftName = null;
		String rightName = null;
		if (null != left) {
			leftName = left.getName();
		}
		
		if (null != right) {
			rightName = right.getName();
		}
		
		return StringUtils.equals(leftName, rightName);
	}
	
	@Override
	public void delete(Student bean) {

	}

	@Override
	public void restore(Student bean) {

	}

	@Override
	public Student find(Student bean) {
		
		try {
			return studentMapper.find(bean);
		}
		catch (RuntimeException e) {
			logger.error("system error", e);
			throw new StudentException("查询学生信息失败", e);
		}
	}

	@Override
	public PageInfo<Student> findList(Student bean, Product product, Integer pageNum, Integer pageSize) {
		
		try {
			if (null != pageNum && null != pageSize) {
				PageHelper.startPage(pageNum, pageSize);				
			}
			return new PageInfo<Student>(studentMapper.findList(bean, product));
		}
		catch (RuntimeException e) {
			logger.error("system error", e);
			throw new StudentException("查询学生列表失败", e);
		}
	}

	@Override
	public void export(Student bean, Product product, OutputStream out) {
		
		// 获取模板文件的路径
		String path = ProjectUtil.getRealPath() + 
				ConfigUtil.getKey("excelDemoPath") + File.separator + "student-demo.xlsx";
		try(InputStream is = new FileInputStream(path)) {
			PageInfo<Student> page = findList(bean, product, null, null);
			
			ExcelUtil.init(is).sheetAt(0).rowAt(3).export(page.getList(), out, (Student t, Row row) -> {
				Classes clazz = t.getClasses();
				if (null != clazz) {
					row.createCell(0).setValue(clazz.getName());					
				}
				row.createCell(1).setValue(t.getId());
				row.createCell(2).setValue(t.getName());
				
				String sex = "女";
				if (StringUtils.equals(t.getSex(), "0")) {
					sex = "男";
				}
				row.createCell(3).setValue(sex);
				
				row.createCell(4).setValue(t.getIdNumber());
				row.createCell(5).setValue(t.getTel());
				row.createCell(6).setValue(t.getEducation().getName());
				row.createCell(7).setValue(t.getSchool());
				row.createCell(8).setValue(t.getMajor());
				row.createCell(9).setValue(t.getAddress());
				row.createCell(10).setValue(t.getEmergent());
				row.createCell(11).setValue(t.getEmergentContact());
				row.createCell(12).setValue(t.getPreviousJob());
				row.createCell(13).setValue(t.getJoinWay());
				
				String joinDate = DateUtil.format(t.getJoinDate(), DateUtil.FormatStr10);
				row.createCell(14).setValue(joinDate);
				row.createCell(15).setValue(t.getIntentionalCity());
				row.createCell(16).setValue(t.getEmail());
				row.createCell(17).setValue(t.getPassCheck());
				row.createCell(18).setValue(t.getTextBoxId());
				row.createCell(19).setValue(t.getJobIntention());
				row.createCell(20).setValue(t.getAbnormal());
				row.createCell(21).setValue(t.getEvaluate());
				row.createCell(22).setValue(t.getRemarks());
			}).close();
		}
		catch (RuntimeException e) {
			logger.error("导出失败", e);
			throw new StudentException("导出失败", e);
		} 
		catch (FileNotFoundException e) {
			logger.error("模板文件不存在", e);
			throw new StudentException("模板文件不存在", e);
		} 
		catch (IOException e) {
			logger.error("操作文件失败", e);
			throw new StudentException("操作文件失败", e);
		}
	}

	@Override
	@Transactional
	public void importStudent(InputStream is) {
		
		ExcelUtil.init(is).sheetAt(0).rowAt(3).accept((Row row) -> {
			// 从1开始的行号
			int rowNum = row.getRowAt() + 1;
			
			try {
				accept(row);
			}
			catch (RuntimeException e) {
				logger.debug("导入失败", e);
				throw new StudentException("第" + rowNum + "行:" + e.getMessage(), e);
			}
		}).close();
		
		systemLogger.record(LogType.AddType, "批量导入学生信息");
	}
	
	/**
	 * 处理导入的数据
	 * @param row
	 */
	private void accept(Row row) {
		
		Student bean = new Student();
		String className = row.getCell(0).getValue();
		Classes clazz = new Classes();
		if (StringUtils.isNotEmpty(className)) {
			clazz.setName(className);
		}
		bean.setClasses(clazz);
		
		String id = row.getCell(1).getValue();
		if (StringUtils.isEmpty(id)) {
			throw new StudentException("学员编号不能为空");
		}
		bean.setId(id);
		
		String name = row.getCell(2).getValue();
		if (StringUtils.isEmpty(name)) {
			throw new StudentException("学员姓名不能为空");
		}
		bean.setName(name);
		
		String sex = row.getCell(3).getValue();
		if (StringUtils.equals("男", sex)) {
			sex = "0";
		}
		else if (StringUtils.equals("女", sex)) {
			sex = "1";
		}
		else {
			throw new StudentException("性别设置错误");
		}
		
		bean.setSex(sex);
		bean.setIdNumber(row.getCell(4).getValue());
		
		String tel = row.getCell(5).getValue();
		if (StringUtils.isEmpty(tel)) {
			throw new StudentException("联系方式不能为空");
		}
		bean.setTel(tel);
		
		String education = row.getCell(6).getValue();
		Integer educationId = null;
		try {
			educationId = dictService.findValue(DictType.EducationType.toInteger(), education);
		}
		catch (StudentException e) {
			throw new StudentException("学历信息错误", e);
		}
		bean.setEducation(Dictionary.make(null, null, educationId));
		
		String school = row.getCell(7).getValue(); 
		if (StringUtils.isEmpty(school)) {
			throw new StudentException("毕业学校不能为空");
		}
		bean.setSchool(school);
		
		String major = row.getCell(8).getValue();
		if (StringUtils.isEmpty(major)) {
			throw new StudentException("专业不能为空");
		}
		bean.setMajor(major);
		
		String address = row.getCell(9).getValue();
		if (StringUtils.isEmpty(address)) {
			throw new StudentException("专业不能为空");
		}
		bean.setAddress(address);
		
		bean.setEmergent(getCellValue(row.getCell(10)));
		bean.setEmergentContact(getCellValue(row.getCell(11)));
		bean.setPreviousJob(getCellValue(row.getCell(12)));
		bean.setJoinWay(getCellValue(row.getCell(13)));
		
		String joinDateStr = row.getCell(14).getValue();
		Date joinDate = DateUtil.parseDate(joinDateStr, DateUtil.FormatStr10);
		// if (null == joinDate) {
		// throw new StudentException("日期格式非法");
		// }
		bean.setJoinDate(joinDate);
		
		String intentionalCity = row.getCell(15).getValue();
		if (StringUtils.isEmpty(intentionalCity)) {
			throw new StudentException("意向城市不能为空");
		}
		bean.setIntentionalCity(intentionalCity);
		
		try {
			String email = row.getCell(16).getValue();
			Verify.verifyEmail(email);
			bean.setEmail(email);
		}
		catch (VerifyException e) {
			throw new StudentException("邮箱格式错误", e);
		}
		
		String passCheck = row.getCell(17).getValue();
		if (StringUtils.isEmpty(passCheck)) {
			throw new StudentException("通行证不能为空");
		}
		bean.setPassCheck(passCheck);
		
		// 非必填项
		Cell cell = row.getCell(18);
		bean.setTextBoxId(getCellValue(cell));
		cell = row.getCell(19);
		bean.setJobIntention(getCellValue(cell));
		cell = row.getCell(20);
		bean.setAbnormal(getCellValue(cell));
		cell = row.getCell(21);
		bean.setEvaluate(getCellValue(cell));
		cell = row.getCell(22);
		bean.setRemarks(getCellValue(cell));
		
		try {
			StudentController.validate(bean);
		}
		catch (VerifyException e) {
			throw new StudentException("参数非法." + e.getMessage(), e);
		}
		
		insert(bean);
	}
	
	/**
	 * 获取可能为null的cell中的值
	 * @param cell
	 * @return
	 */
	private String getCellValue(Cell cell) {
		if (null != cell) {
			return cell.getValue();
		}
		return null;
	}
}
